home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / gnustuff / tos / othergnu / indent~1.zoo / io.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-20  |  21.3 KB  |  881 lines

  1. /* Copyright (c) 1992, Free Software Foundation, Inc.  All rights reserved.
  2.  
  3.    Copyright (c) 1985 Sun Microsystems, Inc. Copyright (c) 1980 The Regents
  4.    of the University of California. Copyright (c) 1976 Board of Trustees of
  5.    the University of Illinois. All rights reserved.
  6.  
  7.    Redistribution and use in source and binary forms are permitted
  8.    provided that
  9.    the above copyright notice and this paragraph are duplicated in all such
  10.    forms and that any documentation, advertising materials, and other
  11.    materials related to such distribution and use acknowledge that the
  12.    software was developed by the University of California, Berkeley, the
  13.    University of Illinois, Urbana, and Sun Microsystems, Inc.  The name of
  14.    either University or Sun Microsystems may not be used to endorse or
  15.    promote products derived from this software without specific prior written
  16.    permission. THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  17.    IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES
  18.    OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
  19.  
  20.  
  21. #include "sys.h"
  22. #include "indent.h"
  23. #include <ctype.h>
  24.  
  25. /* POSIX says that <fcntl.h> should exist.  Some systems might need to use
  26.    <sys/fcntl.h> or <sys/file.h> instead.  */
  27. #include <fcntl.h>
  28.  
  29. #include <sys/types.h>
  30. #include <sys/stat.h>
  31.  
  32. /* number of levels a label is placed to left of code */
  33. #define LABEL_OFFSET 2
  34.  
  35.  
  36. /* Stuff that needs to be shared with the rest of indent. Documented in
  37.    indent.h.  */
  38. char *in_prog;
  39. char *in_prog_pos;
  40. char *cur_line;
  41. unsigned int in_prog_size;
  42. FILE *output;
  43. char *buf_ptr;
  44. char *buf_end;
  45. int had_eof;
  46. int out_lines;
  47. int com_lines;
  48.  
  49. int suppress_blanklines = 0;
  50. int comment_open;
  51.  
  52. int paren_target;
  53.  
  54. /* Use `perror' to print the system error message
  55.    caused by OFFENDER. */
  56.  
  57. static char *errbuf;
  58.  
  59. void
  60. sys_error (offender)
  61.      char *offender;
  62. {
  63.   int size = strlen (offender);
  64.   static int buffer_size;
  65.  
  66.   if (errbuf == 0)
  67.     {
  68.       buffer_size = size + 10;    /* Extra for random unix lossage */
  69.       errbuf = (char *) xmalloc (buffer_size);
  70.     }
  71.   else if (size + 10 > buffer_size)
  72.     {
  73.       buffer_size = size + 10;
  74.       errbuf = xrealloc (errbuf, buffer_size);
  75.     }
  76.   sprintf (errbuf, "indent: %s", offender);
  77.   perror (errbuf);
  78.   exit (1);
  79. }
  80.  
  81. /* true if INDENT OFF is in effect */
  82. static int inhibit_formatting;
  83.  
  84. void
  85. dump_line ()
  86. {                /* dump_line is the routine that actually
  87.                    effects the printing of the new source. It
  88.                    prints the label section, followed by the
  89.                    code section with the appropriate nesting
  90.                    level, followed by any comments */
  91.   register int cur_col;
  92.   register int target_col = 0;
  93.   static not_first_line;
  94.  
  95.   if (parser_state_tos->procname[0])
  96.     {
  97.       if (troff)
  98.     {
  99.       if (comment_open)
  100.         {
  101.           comment_open = 0;
  102.           fprintf (output, ".*/\n");
  103.         }
  104.       fprintf (output, ".Pr \"%.*s\"\n", parser_state_tos->procname_end - parser_state_tos->procname,
  105.            parser_state_tos->procname);
  106.     }
  107.       parser_state_tos->ind_level = 0;
  108.       parser_state_tos->procname = "\0";
  109.     }
  110.  
  111.   /* A blank line */
  112.   if (s_code == e_code && s_lab == e_lab && s_com == e_com)
  113.     {
  114.       /* If we have a formfeed on a blank line, we should just output it,
  115.          rather than treat it as a normal blank line.  */
  116.       if (parser_state_tos->use_ff)
  117.     {
  118.       putc ('\014', output);
  119.       parser_state_tos->use_ff = false;
  120.     }
  121.       else
  122.     {
  123.       if (suppress_blanklines > 0)
  124.         suppress_blanklines--;
  125.       else
  126.         {
  127.           parser_state_tos->bl_line = true;
  128.           n_real_blanklines++;
  129.         }
  130.     }
  131.     }
  132.   else if (!inhibit_formatting)
  133.     {
  134.       suppress_blanklines = 0;
  135.       parser_state_tos->bl_line = false;
  136.       if (prefix_blankline_requested && not_first_line)
  137.     {
  138.       if (swallow_optional_blanklines && n_real_blanklines > 1)
  139.         n_real_blanklines = 1;
  140.       else if (n_real_blanklines == 0)
  141.         n_real_blanklines = 1;
  142.     }
  143.  
  144.       while (--n_real_blanklines >= 0)
  145.     putc ('\n', output);
  146.       n_real_blanklines = 0;
  147.       if (parser_state_tos->ind_level == 0)
  148.     parser_state_tos->ind_stmt = 0;    /* this is a class A kludge. dont do
  149.                        additional statement indentation
  150.                        if we are at bracket level 0 */
  151.  
  152.       if (e_lab != s_lab || e_code != s_code)
  153.     ++code_lines;        /* keep count of lines with code */
  154.  
  155.  
  156.       if (e_lab != s_lab)
  157.     {            /* print lab, if any */
  158.       if (comment_open)
  159.         {
  160.           comment_open = 0;
  161.           fprintf (output, ".*/\n");
  162.         }
  163.       while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
  164.         e_lab--;
  165.       cur_col = pad_output (1, compute_label_target ());
  166.       if (s_lab[0] == '#' && (strncmp (s_lab, "#else", 5) == 0
  167.                   || strncmp (s_lab, "#endif", 6) == 0))
  168.         {
  169.           /* Treat #else and #endif as a special case because any text
  170.              after #else or #endif should be converted to a comment.  */
  171.           register char *s = s_lab;
  172.           if (e_lab[-1] == '\n')
  173.         e_lab--;
  174.           do
  175.         putc (*s++, output);
  176.           while (s < e_lab && 'a' <= *s && *s <= 'z');
  177.           while ((*s == ' ' || *s == '\t') && s < e_lab)
  178.         s++;
  179.           if (s < e_lab)
  180.         fprintf (output, s[0] == '/' && s[1] == '*' ? "\t%.*s" : "\t/* %.*s */",
  181.              e_lab - s, s);
  182.         }
  183.       else
  184.         fprintf (output, "%.*s", e_lab - s_lab, s_lab);
  185.       cur_col = count_spaces (cur_col, s_lab);
  186.     }
  187.       else
  188.     cur_col = 1;        /* there is no label section */
  189.  
  190.       parser_state_tos->pcase = false;
  191.  
  192.       if (s_code != e_code)
  193.     {            /* print code section, if any */
  194.       register char *p;
  195.  
  196.       if (comment_open)
  197.         {
  198.           comment_open = 0;
  199.           fprintf (output, ".*/\n");
  200.         }
  201.       target_col = compute_code_target ();
  202.       /* If a line ends in an lparen character, the following line should
  203.          not line up with the parenthesis, but should be indented by the
  204.          usual amount.  */
  205.       if (parser_state_tos->last_token == lparen)
  206.         {
  207.           parser_state_tos->paren_indents[parser_state_tos->p_l_follow - 1]
  208.         += ind_size - 1;
  209.         }
  210.       {
  211.         register i;
  212.  
  213.         for (i = 0; i < parser_state_tos->p_l_follow; i++)
  214.           if (parser_state_tos->paren_indents[i] >= 0)
  215.         parser_state_tos->paren_indents[i]
  216.           = -(parser_state_tos->paren_indents[i] + target_col);
  217.       }
  218.       cur_col = pad_output (cur_col, target_col);
  219.       for (p = s_code; p < e_code; p++)
  220.         if (*p == (char) 0200)
  221.           fprintf (output, "%d", target_col * 7);
  222.         else
  223.           putc (*p, output);
  224.       cur_col = count_spaces (cur_col, s_code);
  225.     }
  226.  
  227.       if (s_com != e_com)
  228.     {
  229.       if (troff)
  230.         {
  231.           int all_here = 0;
  232.           register char *p;
  233.  
  234.           if (e_com[-1] == '/' && e_com[-2] == '*')
  235.         e_com -= 2, all_here++;
  236.           while (e_com > s_com && e_com[-1] == ' ')
  237.         e_com--;
  238.           *e_com = 0;
  239.           p = s_com;
  240.           while (*p == ' ')
  241.         p++;
  242.           if (p[0] == '/' && p[1] == '*')
  243.         p += 2, all_here++;
  244.           else if (p[0] == '*')
  245.         p += p[1] == '/' ? 2 : 1;
  246.           while (*p == ' ')
  247.         p++;
  248.           if (*p == 0)
  249.         goto inhibit_newline;
  250.           if (comment_open < 2 && parser_state_tos->box_com)
  251.         {
  252.           comment_open = 0;
  253.           fprintf (output, ".*/\n");
  254.         }
  255.           if (comment_open == 0)
  256.         {
  257.           if ('a' <= *p && *p <= 'z')
  258.             *p = *p + 'A' - 'a';
  259.           if (e_com - p < 50 && all_here == 2)
  260.             {
  261.               register char *follow = p;
  262.               fprintf (output, "\n.nr C! \\w\1");
  263.               while (follow < e_com)
  264.             {
  265.               switch (*follow)
  266.                 {
  267.                 case '\n':
  268.                   putc (' ', output);
  269.                 case 1:
  270.                   break;
  271.                 case '\\':
  272.                   putc ('\\', output);
  273.                 default:
  274.                   putc (*follow, output);
  275.                 }
  276.               follow++;
  277.             }
  278.               putc (1, output);
  279.             }
  280.           fprintf (output, "\n./* %dp %d %dp\n",
  281.                parser_state_tos->com_col * 7,
  282.                (s_code != e_code || s_lab != e_lab) - parser_state_tos->box_com,
  283.                target_col * 7);
  284.         }
  285.           comment_open = 1 + parser_state_tos->box_com;
  286.           while (*p)
  287.         {
  288.           if (*p == BACKSLASH)
  289.             putc (BACKSLASH, output);
  290.           putc (*p++, output);
  291.         }
  292.         }
  293.       else
  294.         {            /* print comment, if any */
  295.           register target = parser_state_tos->com_col;
  296.           register char *com_st = s_com;
  297.  
  298.           target += parser_state_tos->comment_delta;
  299.           while (*com_st == '\t')
  300.         com_st++, target += tabsize;
  301.  
  302.           while (target <= 0)
  303.         if (*com_st == ' ')
  304.           target++, com_st++;
  305.         else if (*com_st == '\t')
  306.           {
  307.             target = ((target - 1) & ~(tabsize - 1)) + (tabsize + 1);
  308.             com_st++;
  309.           }
  310.         else
  311.           target = 1;
  312.           if (cur_col > target)
  313.         {        /* if comment cant fit on this line, put it
  314.                    on next line */
  315.           putc ('\n', output);
  316.           cur_col = 1;
  317.           ++out_lines;
  318.         }
  319.           while (e_com > com_st && isspace (e_com[-1]))
  320.         e_com--;
  321.           cur_col = pad_output (cur_col, target);
  322.           if (!parser_state_tos->box_com)
  323.         {
  324.           if (star_comment_cont
  325.               && (com_st[1] != '*' || e_com <= com_st + 1))
  326.             if (com_st[1] == ' '
  327.             && com_st[0] == ' ' && e_com > com_st + 1)
  328.               com_st[1] = '*';
  329.             else
  330.               fwrite (" * ", (com_st[0] == '\t'
  331.                       ? 2 : (com_st[0] == '*' ? 1 : 3)),
  332.                   1, output);
  333.         }
  334.           fwrite (com_st, e_com - com_st, 1, output);
  335.           parser_state_tos->comment_delta
  336.         = parser_state_tos->n_comment_delta;
  337.           cur_col = count_spaces (cur_col, com_st);
  338.           ++com_lines;    /* count lines with comments */
  339.         }
  340.     }
  341.  
  342.       if (parser_state_tos->use_ff)
  343.     {
  344.       putc ('\014', output);
  345.       parser_state_tos->use_ff = false;
  346.     }
  347.       else
  348.     putc ('\n', output);
  349.     inhibit_newline:
  350.       ++out_lines;
  351.       if (parser_state_tos->just_saw_decl == 1
  352.       && blanklines_after_declarations)
  353.     {
  354.       prefix_blankline_requested = 1;
  355.       parser_state_tos->just_saw_decl = 0;
  356.     }
  357.       else
  358.     prefix_blankline_requested = postfix_blankline_requested;
  359.       postfix_blankline_requested = 0;
  360.     }
  361.  
  362.   /* if we are in the middle of a declaration, remember that fact
  363.      for proper comment indentation */
  364.   parser_state_tos->decl_on_line = parser_state_tos->in_decl;
  365.  
  366.   /* next line should be indented if we have not completed this
  367.      stmt and if we are not in the middle of a declaration */
  368.   parser_state_tos->ind_stmt = (parser_state_tos->in_stmt
  369.                 & ~parser_state_tos->in_decl);
  370.  
  371.   parser_state_tos->dumped_decl_indent = 0;
  372.   *(e_lab = s_lab) = '\0';    /* reset buffers */
  373.   *(e_code = s_code) = '\0';
  374.   *(e_com = s_com) = '\0';
  375.   parser_state_tos->ind_level = parser_state_tos->i_l_follow;
  376.   parser_state_tos->paren_level = parser_state_tos->p_l_follow;
  377.   if (parser_state_tos->paren_level > 0)
  378.     paren_target
  379.       = -parser_state_tos->paren_indents[parser_state_tos->paren_level - 1];
  380.   else
  381.     paren_target = 0;
  382.   not_first_line = 1;
  383.   return;
  384. }
  385.  
  386. /* Figure out where we should put the code in codebuf. Return the column
  387.    number in spaces.  */
  388.  
  389. INLINE int
  390. compute_code_target ()
  391. {
  392.   register target_col = parser_state_tos->ind_level + 1;
  393.  
  394.   if (parser_state_tos->paren_level)
  395.     if (!lineup_to_parens)
  396.       target_col += continuation_indent * parser_state_tos->paren_level;
  397.     else
  398.       {
  399.     register w;
  400.     register t = paren_target;
  401.  
  402.     if ((w = count_spaces (t, s_code) - max_col) > 0
  403.         && count_spaces (target_col, s_code) <= max_col)
  404.       {
  405.         t -= w + 1;
  406.         if (t > target_col)
  407.           target_col = t;
  408.       }
  409.     else
  410.       target_col = t;
  411.       }
  412.   else if (parser_state_tos->ind_stmt)
  413.     target_col += continuation_indent;
  414.   return target_col;
  415. }
  416.  
  417. INLINE int
  418. compute_label_target ()
  419. {
  420.   return
  421.   parser_state_tos->pcase ? case_ind + 1
  422.   : *s_lab == '#' ? 1
  423.   : parser_state_tos->ind_level - LABEL_OFFSET + 1;
  424. }
  425.  
  426. /* Read file FILENAME into a `fileptr' structure, and return a pointer to
  427.    that structure. */
  428.  
  429. static struct file_buffer fileptr;
  430.  
  431. struct file_buffer *
  432. read_file (filename)
  433.      char *filename;
  434. {
  435. #ifdef atarist
  436.   int n;
  437. #endif
  438.   int fd;
  439.   struct stat file_stats;
  440.   int namelen = strlen (filename);
  441.  
  442.   fd = open (filename, O_RDONLY, 0777);
  443.   if (fd < 0)
  444.     sys_error (filename);
  445.  
  446.   if (fstat (fd, &file_stats) < 0)
  447.     sys_error (filename);
  448.  
  449.   if (fileptr.data != 0)
  450.     free (fileptr.data);
  451.   fileptr.size = file_stats.st_size;
  452.   fileptr.data = (char *) xmalloc (file_stats.st_size + 1);
  453.  
  454.   if (read (fd, fileptr.data, fileptr.size) < 0)
  455.     sys_error (filename);
  456.  
  457.   if (close (fd) < 0)
  458.     sys_error (filename);
  459.   
  460. #ifdef atarist
  461.   for (n = 0; (n + 1) < fileptr.size; n++)
  462.   {
  463.     if (fileptr.data[n] == '\x0d' && fileptr.data[n + 1] == '\x0a')
  464.     {
  465.         fileptr.data[n] = '\x0a';
  466.         memmove(&fileptr.data[n + 1], &fileptr.data[n + 2], fileptr.size
  467.                 - n - 2);
  468.         fileptr.size--;
  469.     }
  470.   }
  471. #endif
  472.  
  473.   fileptr.name = (char *) xmalloc (namelen + 1);
  474.   memcpy (fileptr.name, filename, namelen);
  475.   fileptr.name[namelen] = '\0';
  476.  
  477.   fileptr.data[fileptr.size] = '\0';
  478.  
  479.   return &fileptr;
  480. }
  481.  
  482. /* This should come from stdio.h and be some system-optimal number */
  483. #ifndef BUFSIZ
  484. #define BUFSIZ 1024
  485. #endif
  486.  
  487. /* Suck the standard input into a file_buffer structure, and
  488.    return a pointer to that structure. */
  489.  
  490. struct file_buffer stdinptr;
  491.  
  492. struct file_buffer *
  493. read_stdin ()
  494. {
  495.   unsigned int size = 15 * BUFSIZ;
  496.   int ch;
  497.   register char *p;
  498.  
  499.   if (stdinptr.data != 0)
  500.     free (stdinptr.data);
  501.  
  502.   stdinptr.data = (char *) xmalloc (size + 1);
  503.   stdinptr.size = 0;
  504.   p = stdinptr.data;
  505.   do
  506.     {
  507.       while (stdinptr.size < size)
  508.     {
  509.       ch = getc (stdin);
  510.       if (ch == EOF)
  511.         break;
  512.  
  513.       *p++ = ch;
  514.       stdinptr.size++;
  515.     }
  516.  
  517.       if (ch != EOF)
  518.     {
  519.       size += (2 * BUFSIZ);
  520.       stdinptr.data = xrealloc (stdinptr.data, size);
  521.     }
  522.     }
  523.   while (ch != EOF);
  524.  
  525.   stdinptr.name = "Standard Input";
  526.  
  527.   stdinptr.data[stdinptr.size] = '\0';
  528.  
  529.   return &stdinptr;
  530. }
  531.  
  532. /* Advance buf_ptr so that it points to the next line of input.  Skip over
  533.    indent errors (comments beginning with *INDENT**), ignoring them.  Process
  534.    INDENT ON and INDENT OFF. (Note: the name of this function is a historical
  535.    artifact from before the time that indent kept the whole source file in
  536.    memory). */
  537.  
  538. INLINE void
  539. fill_buffer ()
  540. {
  541.   /* Point various places in the buffer.  */
  542.   register char *p;
  543.  
  544.   /* Character P points to. */
  545.   register char c;
  546.  
  547.   /* Have we found INDENT ON or INDENT OFF ? */
  548.   enum
  549.     {
  550.       None, Indent_on, Indent_off
  551.     } com;
  552.  
  553.   /* indent() may be saving the text between "if (...)" and the following
  554.      statement.  To do so, it uses another buffer (`save_com').  Switch
  555.      back to the previous buffer here. */
  556.   if (bp_save != 0)
  557.     {
  558.       buf_ptr = bp_save;
  559.       buf_end = be_save;
  560.       bp_save = be_save = 0;
  561.  
  562.       /* only return if there is really something in this buffer */
  563.       if (buf_ptr < buf_end)
  564.     return;
  565.     }
  566.  
  567. fill_it:
  568.  
  569.   cur_line = in_prog_pos;
  570.   buf_ptr = in_prog_pos;
  571.   if (*buf_ptr == '\0')
  572.     {
  573.       had_eof = true;
  574.       return;
  575.     }
  576.  
  577.   p = buf_ptr;
  578.   do
  579.     {
  580.       c = *p;
  581.       p++;
  582.     }
  583.   while (c != '\0' && c != '\n');
  584.   buf_end = p;
  585.  
  586.   p = buf_ptr;
  587.   in_prog_pos = buf_end;
  588.  
  589.   while (*p == ' ' || *p == '\t')
  590.     p++;
  591.   if (*p == '/' && p[1] == '*')
  592.     {
  593.       p += 2;
  594.       if (p[1] == 'I' && strncmp (p, "*INDENT**", 9) == 0)
  595.     goto fill_it;
  596.       while (*p == ' ' || *p == '\t')
  597.     p++;
  598.       com = None;
  599.       if (p[0] == 'I' && p[1] == 'N' && p[2] == 'D' && p[3] == 'E'
  600.       && p[4] == 'N' && p[5] == 'T')
  601.     {
  602.       p += 6;
  603.       while (*p == ' ' || *p == '\t')
  604.         p++;
  605.       if (*p == '*')
  606.         com = Indent_on;
  607.       else if (*p == 'O')
  608.         if (*++p == 'N')
  609.           p++, com = Indent_on;
  610.         else if (*p == 'F' && *++p == 'F')
  611.           p++, com = Indent_off;
  612.       while (*p == ' ' || *p == '\t')
  613.         p++;
  614.       if (p[0] == '*' && p[1] == '/' && p[2] == '\n' && com)
  615.         {
  616.           if (s_com != e_com || s_lab != e_lab || s_code != e_code)
  617.         dump_line ();
  618.           if (!(inhibit_formatting = (int) com - 1))
  619.         {
  620.           n_real_blanklines = 0;
  621.           postfix_blankline_requested = 0;
  622.           prefix_blankline_requested = 0;
  623.           suppress_blanklines = 1;
  624.         }
  625.         }
  626.     }
  627.     }
  628.   if (inhibit_formatting)
  629.     {
  630.       p = buf_ptr;
  631.       do
  632.     putc (*p, output);
  633.       while (*p++ != '\n');
  634.     }
  635.  
  636. }
  637.  
  638.  
  639. /* Copyright (C) 1976 by the Board of Trustees of the University of Illinois
  640.  
  641. All rights reserved
  642.  
  643.  
  644. NAME: pad_output
  645.  
  646. FUNCTION: Writes tabs and spaces to move the current column up to the desired
  647.    position.
  648.  
  649. ALGORITHM: Put tabs and/or blanks into pobuf, then write pobuf.
  650.  
  651. PARAMETERS: current        integer        The current column target
  652.    nteger        The desired column
  653.  
  654. RETURNS: Integer value of the new column.  (If current >= target, no action
  655.    is taken, and current is returned.
  656.  
  657. GLOBALS: None
  658.  
  659. CALLS: write (sys)
  660.  
  661. CALLED BY: dump_line
  662.  
  663. HISTORY: initial coding     November 1976    D A Willcox of CAC */
  664.  
  665. INLINE int
  666. pad_output (current, target)    /* writes tabs and blanks (if necessary) to
  667.                    get the current output position up to the
  668.                    target column */
  669.      int current;        /* the current column value */
  670.      int target;        /* position we want it at */
  671. {
  672.   register int curr;        /* internal column pointer */
  673.   register int tcur;
  674.  
  675.   if (troff)
  676.     fprintf (output, "\\h'|%dp'", (target - 1) * 7);
  677.   else
  678.     {
  679.       if (current >= target)
  680.     return (current);    /* line is already long enough */
  681.       curr = current;
  682.       while ((tcur = curr + tabsize - (curr - 1) % tabsize) <= target)
  683.     {
  684.       putc ('\t', output);
  685.       curr = tcur;
  686.     }
  687.       while (curr++ < target)
  688.     putc (' ', output);    /* pad with final blanks */
  689.     }
  690.   return (target);
  691. }
  692.  
  693. /* Copyright (C) 1976 by the Board of Trustees of the University of Illinois
  694.  
  695. All rights reserved
  696.  
  697.  
  698. NAME: count_spaces
  699.  
  700. FUNCTION: Find out where printing of a given string will leave the current
  701.    character position on output.
  702.  
  703. ALGORITHM: Run thru input string and add appropriate values to current
  704.    position.
  705.  
  706. RETURNS: Integer value of position after printing "buffer" starting in column
  707.    "current".
  708.  
  709. HISTORY: initial coding     November 1976    D A Willcox of CAC */
  710.  
  711. INLINE int
  712. count_spaces (current, buffer)
  713.      /* this routine figures out where the character position will be after
  714.         printing the text in buffer starting at column "current" */
  715.      int current;
  716.      char *buffer;
  717. {
  718.   register char *buf;        /* used to look thru buffer */
  719.   register int cur;        /* current character counter */
  720.  
  721.   cur = current;
  722.  
  723.   for (buf = buffer; *buf != '\0'; ++buf)
  724.     {
  725.       switch (*buf)
  726.     {
  727.  
  728.     case '\n':
  729.     case 014:        /* form feed */
  730.       cur = 1;
  731.       break;
  732.  
  733.     case '\t':
  734.       cur = cur + tabsize - (cur - 1) % tabsize;
  735.       break;
  736.  
  737.     case 010:        /* backspace */
  738.       --cur;
  739.       break;
  740.  
  741.     default:
  742.       ++cur;
  743.       break;
  744.     }            /* end of switch */
  745.     }                /* end of for loop */
  746.   return (cur);
  747. }
  748.  
  749. /* Nonzero if we have found an error (not a warning).  */
  750. int found_err;
  751.  
  752. /* Signal an error.  LEVEL is nonzero if it is an error (as opposed to a
  753.    warning.  MSG is a printf-style format string.  Additional arguments are
  754.    additional arguments for printf.  */
  755. /* VARARGS2 */
  756. diag (level, msg, a, b)
  757.      int level;
  758.      unsigned int a, b;
  759.      char *msg;
  760. {
  761.   if (level)
  762.     found_err = 1;
  763.   if (output == stdout)
  764.     {
  765.       fprintf (stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no);
  766.       fprintf (stdout, msg, a, b);
  767.       fprintf (stdout, " */\n");
  768.     }
  769.   else
  770.     {
  771.       fprintf (stderr, "%s: %d: ", in_name, line_no);
  772.       fprintf (stderr, msg, a, b);
  773.       fprintf (stderr, "\n");
  774.     }
  775. }
  776.  
  777. writefdef (f, nm)
  778.      register struct fstate *f;
  779.      unsigned int nm;
  780. {
  781.   fprintf (output, ".ds f%c %s\n.nr s%c %d\n",
  782.        nm, f->font, nm, f->size);
  783. }
  784.  
  785. /* Write characters starting at S to change the font from OF to NF.  Return a
  786.    pointer to the character after the last character written. For troff mode
  787.    only.  */
  788. char *
  789. chfont (of, nf, s)
  790.      register struct fstate *of, *nf;
  791.      char *s;
  792. {
  793.   if (of->font[0] != nf->font[0]
  794.       || of->font[1] != nf->font[1])
  795.     {
  796.       *s++ = '\\';
  797.       *s++ = 'f';
  798.       if (nf->font[1])
  799.     {
  800.       *s++ = '(';
  801.       *s++ = nf->font[0];
  802.       *s++ = nf->font[1];
  803.     }
  804.       else
  805.     *s++ = nf->font[0];
  806.     }
  807.   if (nf->size != of->size)
  808.     {
  809.       *s++ = '\\';
  810.       *s++ = 's';
  811.       if (nf->size < of->size)
  812.     {
  813.       *s++ = '-';
  814.       *s++ = '0' + of->size - nf->size;
  815.     }
  816.       else
  817.     {
  818.       *s++ = '+';
  819.       *s++ = '0' + nf->size - of->size;
  820.     }
  821.     }
  822.   return s;
  823. }
  824.  
  825. void
  826. parsefont (f, s0)
  827.      register struct fstate *f;
  828.      char *s0;
  829. {
  830.   register char *s = s0;
  831.   int sizedelta = 0;
  832.   int i;
  833.  
  834.   f->size = 0;
  835.   f->allcaps = 1;
  836.   for (i = 0; i < 4; i++)
  837.     f->font[i] = 0;
  838.  
  839.   while (*s)
  840.     {
  841.       if (isdigit (*s))
  842.     f->size = f->size * 10 + *s - '0';
  843.       else if (isupper (*s))
  844.     if (f->font[0])
  845.       f->font[1] = *s;
  846.     else
  847.       f->font[0] = *s;
  848.       else if (*s == 'c')
  849.     f->allcaps = 1;
  850.       else if (*s == '+')
  851.     sizedelta++;
  852.       else if (*s == '-')
  853.     sizedelta--;
  854.       else
  855.     {
  856.       fprintf (stderr, "indent: bad font specification: %s\n", s0);
  857.       exit (1);
  858.     }
  859.       s++;
  860.     }
  861.   if (f->font[0] == 0)
  862.     f->font[0] = 'R';
  863.   if (bodyf.size == 0)
  864.     bodyf.size = 11;
  865.   if (f->size == 0)
  866.     f->size = bodyf.size + sizedelta;
  867.   else if (sizedelta > 0)
  868.     f->size += bodyf.size;
  869.   else
  870.     f->size = bodyf.size - f->size;
  871. }
  872.  
  873. #ifdef DEBUG
  874. void
  875. dump_debug_line ()
  876. {
  877.   fprintf (output, "\n*** Debug output marker line ***\n");
  878. }
  879.  
  880. #endif
  881.